In a computer system, such as a server, multiple processes may be running concurrently. These processes share the physical memory of the computer system for their memory needs. With reference to FIG. 1A, processes 102, 104, 106, 108, and 110 all share the memory space 112 of the computer system. If the total amount of memory required by the concurrently executing processes is less than the total physical memory available, each process can execute without experiencing memory access related delays. On the other hand, if the total amount of memory required exceeds the total amount of memory available, memory paging occurs in order to ensure that all processes have sufficient memory to execute.
Paging, as is known, involves swapping the contents of physical memory into and out of disk-based storage, such as a hard drive to extend the logical memory available to a process. Because the memory access speed for disk-based storage is significantly slower than for semiconductor-based storage, paging affects the execution speed of the process being paged.
In some cases, it is desirable to guarantee a certain amount of physical memory to a process or a group of processes. In the prior art, different approaches have been taken to ensure that a process or a group of processes has a guaranteed amount of physical memory during execution. The brute force approach involves having a process lock down a certain amount of physical memory, which may then only be used by that particular process. Although this approach ensures that the process will have a guaranteed amount of physical memory, it is inefficient since other processes cannot utilize memory that is locked even if the process that locks down that memory does not truly need all of it at all times for its execution. Secondly, memory locking is a privileged operation that is not available to ordinary applications.
Another approach based on the external page-cache management scheme lets processes have direct control over their share of physical memory through special primitives provided by the operating system. A sophisticated application can exploit this feature to implement a dedicated memory management policy that best suits its requirements. However, this approach is not backward compatible with existing applications since a legacy application may not be aware of such primitives and would be at a disadvantage when executing in an environment wherein other applications directly control their physical memory requirements.
Another approach involves using a special application program to manage physical memory consumption. This program, known as the Resource Manager, queries the operating system periodically to determine the amount of physical memory being used by every process on the system. When the available memory on the system is low the Resource Manager picks processes that are exceeding their share and tries to force them to shrink in size. This is achieved by stopping the selected processes via signals and process priority changes and then relying on the system memory pager to reclaim non-recently referenced pages of physical memory. In this form of control all of the necessary logic is implemented by the Resource Manager program, a user application, and does not require any modifications to the operating system. However, it is not very deterministic and problems can arise, for instance, if a target process has set up its own signal handlers to ignore signals sent from the Resource Manager.
Memory resource grouping represents another approach to address the physical memory control issue. In memory resource grouping, the physical memory is divided into logical blocks called MRGs. Referring now to FIG. 1B, processes 130, 132, and 134 are assigned to MRG 136 of a computer system 150, while processes 138 and 140 are assigned to MRG 142. In dividing the physical memory space into MRGs, the memory utilization of processes associated with one MRG does not impact the memory utilization in another MRG. For example, even if processes 138 and 140 each requires a vast amount of memory and thus a lot of paging activities need to be performed with respect to the memory assigned to MRG 142, the amount of memory available to MRG 136 is not affected. Thus memory resource grouping is a way to provide memory isolation to a group of processes.
Memory resource grouping also has other advantages. A MRG (such as MRG 136) can be set up to import from another MRG or export memory to another MRG. This form of controlled sharing allows the resources of an under-utilized MRG (that is willing to export) to be used by an over-loaded MRG (that has import capability), leading to higher overall physical memory utilization on the computer system.
Unfortunately, memory resource grouping has only been applied thus far to private memory of processes. To further explain this issue, FIG. 2 shows the various memory resource types that may exist in physical memory. With reference to FIG. 2, physical memory may involve kernel memory 202, and user resource types 204. User resource types 204 include process private memory 206, local shared memory 208, and global shared memory 210 (which includes shared text memory 210A and shared library memory 210B).
Kernel memory refers to the memory used by the operating system kernel. User resource types refer to the various memory types that may be involved with process execution. For example, process private memory 206 includes the data memory, stack or heap memory specific to a process during execution. Local shared memory 208 may include, for example, a memory-mapped file segment that is shared between specific processes.
Shared text memory 210A may include, for example, text that is shared by identical copies of programs executing in a computer system (i.e., such global shared memory is not specific to any process or groups of processes). Likewise, shared library memory 210B may include, for example, certain libraries of code that are shared by all processes executing in a computer system.
As shown in FIG. 2, different segments of private memory 206 may be assigned to different MRGs, such as MRGs 220, 222 and 224. These different private memory fragments may be created by different processes, for example.
As mentioned, the paradigm of grouping memory in different MRGs has been confined to private memory thus far. Partitioning private memory is less complicated than partitioning local shared memory or partitioning global shared memory since each private memory segment (or object) is affiliated with only one process. As currently implemented, it is not possible to extend memory resource grouping to either local shared memory or global shared memory.
To elaborate, consider the situation in FIG. 3. In FIG. 3, process 302 and process 304 are affiliated with respective MRGs 352 and 354. These process affiliations are represented by private affiliations 312 and 314 respectively. The private affiliations are typically assigned to the processes, e.g., by the system administrator or by inheritance during forking (i.e., the child process inherits the same affiliation as the parent process after being forked in the unix environment).
Process 302 creates three private segments 302A, 302B, and 302C during execution. These private segments are automatically affiliated (by the operating system) with the MRG 352 since there is a private affiliation 312 between process 302 and MRG 352. Accordingly, the memory required by memory segments 302A, 302B, and 302C are allocated only from MRG 352.
Likewise, process 304 creates three private segments 304A, 304B, and 304C during execution. These private segments are automatically affiliated (by the operating system) with the MRG 354 since there is a private affiliation 314 between process 304 and MRG 354. Accordingly, the memory required by memory segments 304A, 304B, and 304C are allocated only from MRG 354. Logically speaking, each of process 302 and process 304 has been partitioned to use only the memory associated with the MRG to which it is affiliated for its private memory needs (i.e., MRG 352 for process 302 and MRG 354 for process 304).
Now consider the shared memory situation. If process 302 and process 304, which are affiliated with different MRGs for their private memory needs, need to share a memory segment (i.e., either local shared memory or global shared memory), a methodology needs to exist to allow these processes to share a memory segment across the logical partitions that divide the MRGs. Furthermore, a methodology needs to be developed to allow a shared memory segment (either local or global) to be shared by processes even if the process that created that shared memory segment detaches from it or no longer exists. This is unlike the situation with a private memory segment wherein the private memory segment is deallocated if it is detached from its creator process or if its creator process terminates.
Additionally, the sharing needs to be transparent from the load-balancing perspective in that it is important to be able to move a process from one MRG to another MRG without undue restriction even if that process shares a memory segment with another process that may be assigned to any of the MRGs. For example, requiring that processes sharing a memory segment to be assigned to the same MRG would ensure that these processes can share the same memory segment but would impose an undue restriction on the ability to move a process from one MRG to another MRG during load balancing. For backward compatibility reasons, the methodology also needs to work within the existing application semantics and memory resource grouping infrastructure.
The aforementioned related application entitled “MANAGING SHARED MEMORY USAGE WITHIN A MEMORY RESOURCE GROUP INFRASTRUCTURE” is directed toward providing physical memory isolation for shared memory segments. However, unless kernel memory usage can also be managed, it is impossible to meaningfully guarantee, in some cases, physical memory to user memory types (e.g., private memory, local shared memory, or global shared memory) if such a guarantee is desired. This is because typically there is no restriction on memory usage by the kernel and as a result the user memory types may still be starved if the kernel memory is allowed to expand without limits. Additionally, the kernel typically comprises a plurality of kernel subsystems, such as the networking subsystem, the file buffer cache subsystem, the storage subsystem, and the like. If kernel memory control is lacking, one or more kernel subsystem may be memory-starved if another kernel subsystem is allowed to exclusively hold an undue amount of memory.